package socket;

import io.ISRDemo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

public class Server {
    /*
        java.net.ServerSocket
        运行在服务端的ServerSocket主要负责两个工作:
        1:申请服务端口，客户端通过该端口与服务端建立链接
        2:监听服务端口，一旦一个客户端链接便创建一个Socket与该客户端交互

        ServerSocket相当于是某客服的"总机"
     */
    private ServerSocket serverSocket;
    //    private PrintWriter[] allOut = {};
    private Collection<PrintWriter> allOut = new ArrayList<>();

    public Server() {
        try {
            System.out.println("正在启动服务端...");
            serverSocket = new ServerSocket(8088);
            System.out.println("服务器启动 完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            while (true) {
                System.out.println("等待客户端链接...");
                Socket socket = serverSocket.accept();
                System.out.println("一个客户端链接了!");
                //启动一个线程来处理与客户端的交互
                ClientHandler handler = new ClientHandler(socket);
                Thread t = new Thread(handler);
                t.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Server server = new Server();
        server.start();

    }

    /**
     * 该线程任务是负责与指定的客户端进行交互
     */
    private class ClientHandler implements Runnable {
        private Socket socket;
        private String host; //记录远端计算机地址信息;

        public ClientHandler(Socket socket) {
            this.socket = socket;
            host = socket.getInetAddress().getHostAddress();
        }

        public void run() {
            PrintWriter pw = null;
            try {
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);
                OutputStream out = socket.getOutputStream();
                OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
                BufferedWriter bw = new BufferedWriter(osw);
                pw = new PrintWriter(bw, true);

                synchronized (allOut) {
//                    allOut = Arrays.copyOf(allOut, allOut.length + 1);
//                    allOut[allOut.length - 1] = pw;
                    allOut.add(pw);
                }
                sendMessage(host + "上线了，当前在线人数:" + allOut.size());

                String line;
                while ((line = br.readLine()) != null) {
                    sendMessage(host + "说:" + line);
                }
            } catch (IOException e) {
                //当客户端强行关闭，服务端这里readline会抛出异常，这里就可以catch异常
            } finally {
                //将当前pw从allOut中删除
                synchronized (allOut) {
//                    for (int i = 0; i < allOut.length; i++) {
//                        if (pw == allOut[i]) {
//                            allOut[i] = allOut[allOut.length - 1];
//                            allOut = Arrays.copyOf(allOut, allOut.length - 1);
//                            break;
//                        }
//                    }
                    allOut.remove(pw);
                }
                System.out.println(host + "已下线，当前在线人数:" + allOut.size());

                try {
                    socket.close();//关闭socket释放底层资源
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        //广播消息给每一个客户端
        private void sendMessage(String line) {
            System.out.println(line);
            synchronized (allOut) {
//                for (int i = 0; i < allOut.length; i++) {
//                    allOut[i].println(line); //将消息发送给客户端
//                }
                for (PrintWriter pw : allOut) {
                    pw.println(line);
                }
            }
        }
    }
}
